package com.security.manage.user.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.security.manage.user.config.JwtUtil;
import com.security.manage.user.dto.ComboDto;
import com.security.manage.user.dto.UserResp;
import com.security.manage.user.model.*;
import com.security.manage.user.repository.DeptRepository;
import com.security.manage.user.repository.TaskRepository;
import com.security.manage.user.repository.UserRepository;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.Api;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.spring.web.json.Json;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.LongStream;


@RestController
@RequestMapping("/user")
@Api("用户管理")
public class UserController {

    @Resource
    private UserRepository userRepository;

    @Resource
    private DeptRepository deptRepository;

    @Resource
    private TaskRepository taskRepository;

    @Resource
    private JwtUtil jwtUtil;

    @PostMapping("/login")
    public ResData login(@RequestBody LoginReq loginReq){

        User user = userRepository.findByAccount(loginReq.getAccount());
        String md5Password = DigestUtils.md5Hex(loginReq.getPassword().getBytes());
        if (user == null){
            return new ResData(0,"登录失败");
        }

        if (user.getUserType().equals(2)){
            return new ResData(0,"外勤人员不能登录系统");
        }

        if (!md5Password.equals(user.getPassword())){
            return new ResData(0,"用户或者密码错误");
        }

        if (!loginReq.getuKey().equals(user.getUsbKey())){
            return new ResData(0,"UKey验证失败");
        }

        String token = getToken(user);
        Map<String,Object> result = new HashMap<>();
        result.put("token",token);
        result.put("user",user);
        return new ResData(1,"登录成功",result);
    }

    /*private List<Map<String,Object>> getAuth(User user) {
        Set<Role> roles = user.getRoles();
        Set<Permission> permissions = new HashSet<>();
        for (Role r:roles){
            permissions.addAll(r.getPermissions());
        }

        List<Permission> menus = permissions.stream().filter(p -> p.getPid() == -1L).collect(Collectors.toList());
        List<Map<String,Object>> result = new ArrayList<>();
        for (Permission p : menus){
            Long id = p.getId();
            Map<String,Object> map = new HashMap<>();
            map.put("id",p.getId());
            map.put("pid",p.getPid());
            map.put("permName",p.getPermName());
            map.put("permUrl",p.getPermUrl());
            map.put("requestMethod",p.getRequestMethod());
            map.put("permType",p.getPermType());
            map.put("leaf",p.getLeaf());
            List<Permission> subList = permissions.stream().filter(p1 -> p1.getPid() == id).collect(Collectors.toList());
            map.put("subList",subList);
            result.add(map);
        }

        return result;
    }*/

    private String getToken(User user) {
        Map<String,Object> userInfoMap = new HashMap<>();
        userInfoMap.put("userId",user.getId());
        userInfoMap.put("userName",user.getUserName());
        return jwtUtil.createToken(JSON.toJSONString(userInfoMap));
    }

    @GetMapping("/manage/dept")
    public ResData getManageDept(String manageDept){

        if (StringUtils.isEmpty(manageDept)){
            return new ResData(0,"参数异常",null);
        }
        String[] idArray = StringUtils.split(manageDept, ",");
        List<Long> ids = Arrays.stream(idArray)
                .map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
        List<Dept> depts = deptRepository.findAllById(ids);
        List<ComboDto> comboDtos = new ArrayList<>();
        depts.forEach(c -> comboDtos.add(new ComboDto(c.getId(),c.getName())));
        return new ResData<>(1, "获取成功", comboDtos);
    }

    @GetMapping("/uKey")
    public ResData getDataByUKey(String uKey){

        if (StringUtils.isEmpty(uKey)){
            return new ResData(0,"参数异常",null);
        }
        User user = userRepository.findByUsbKey(uKey);
        if (user==null){
            return new ResData(0,"此计算机没有对应的任务信息","");
        }

        Map<String,Object> map = new HashMap<>();
        map.put("userId",user.getId());
        map.put("deptId",user.getDept().getId());
        return new ResData(1,"获取成功",map);
    }

    @PostMapping("/check/token")
    public ResData checkToken(String token){

        if (StringUtils.isBlank(token)){
            return new ResData(0,"token 信息无效");
        }

        Claims claims = jwtUtil.getTokenClaim(token);
        if (claims==null){
            return new ResData(0,"token 已过期");
        }

        Long current = new Date().getTime();
        Long expiration = claims.getExpiration().getTime();
        String subject = claims.getSubject();
        if ((expiration-current)<1200000){
            String refreshToken = jwtUtil.createToken(subject);
            JSONObject jsonObject = JSON.parseObject(subject);
            jsonObject.put("refreshToken",refreshToken);
            return new ResData(1,"鉴权成功", JSON.toJSONString(jsonObject));
        }

        return new ResData(1,"鉴权成功",subject);
    }

    @GetMapping("/combo")
    public ResData computerCombo(){
        List<User> all = userRepository.findAll();
        List<Task> byStatus = taskRepository.findByStatus(0);
        List<User> collect = byStatus.stream().map(Task::getUser).collect(Collectors.toList());
        List<Long> collect1 = collect.stream().map(User::getId).collect(Collectors.toList());
        List<User> collect2 = all.stream().filter(computerInfo -> !collect1.contains(computerInfo.getId())).collect(Collectors.toList());
        List<ComboDto> comboDtos = new ArrayList<>();
        collect2.forEach(c -> comboDtos.add(new ComboDto(c.getId(),c.getUserName())));
        return new ResData<>(1, "获取成功", comboDtos);
    }

    @PostMapping("/stop/{id}")
    public ResData UserStop(@PathVariable Long id){
        Optional<User> byId = userRepository.findById(id);
        if (byId.isPresent()){
            User user = byId.get();
            user.setEnable(false);
            user.setUsbKey("");
            userRepository.save(user);
            return new ResData(1,"修改成功",null);
        }
        return new ResData(0,"用户不存在",null);
    }

    @PostMapping("")
    public ResData addUser(@RequestBody User user,Long deptId){

        if (StringUtils.isEmpty(user.getAccount())) {
            return new ResData(0,"账户不能为空");
        }

        if (StringUtils.isEmpty(user.getUsbKey())) {
            return new ResData(0,"必须要选usbKey,不能为空");
        }

        if (user.getId()==null || user.getId()==0L){
            if (StringUtils.isEmpty(user.getPassword())){
                return new ResData(0,"密码不能为空");
            };
        }


        if (deptId==null||deptId==0) {
            return new ResData(0,"请选择部门和角色");
        }

        if (user.getUserType()==2&&StringUtils.isNotEmpty(user.getManageDept())){
            return new ResData(0,"外勤人员不能有管理部门信息");
        }

        if (user.getUserType()==1&&StringUtils.isEmpty(user.getManageDept())){
            return new ResData(0,"管理人员必须有管理部门信息");
        }
        if (user.getId()!=null){
            Optional<User> user1 = userRepository.findById(user.getId());
            if (user1.isPresent()){
                if (StringUtils.isNotEmpty(user.getPassword())){
                    String s = DigestUtils.md5Hex(user.getPassword());
                    user.setPassword(s);
                }else{
                    user.setPassword(user1.get().getPassword());
                }
            }
        }else{
            String s = DigestUtils.md5Hex(user.getPassword());
            user.setPassword(s);
        }

        Dept dept = new Dept(deptId);
        user.setDept(dept);
        userRepository.save(user);
        return new ResData(1,"成功");
    }

    @DeleteMapping("/{id}")
    public ResData delUser(@PathVariable("id") Long id){
        userRepository.deleteById(id);
        return new ResData(1,"成功");
    }

    @GetMapping("/{id}")
    public ResData getUser(@PathVariable("id") Long id){
        Optional<User> optionalDept = userRepository.findById(id);
        return optionalDept.map(dept -> new ResData<>(1, "获取成功", dept)).orElseGet(() -> new ResData(0, "获取失败"));
    }

    @GetMapping("/list")
    public ResData listUser(@RequestParam(value = "page",defaultValue = "0") Integer page,
                           @RequestParam(value = "size",defaultValue = "10") Integer size){

        Sort sort = Sort.by(Sort.Direction.DESC, "id");
        PageRequest of = PageRequest.of(page, size, sort);
        Page<User> pages = userRepository.findAll(of);

        Map<String,Object> map = new HashMap<>();
        map.put("total",pages.getTotalElements());
        List<User> collect = pages.get().collect(Collectors.toList());
        List<UserResp> result = new ArrayList<>();
        for (User user :collect){
            UserResp resp = new UserResp();
            BeanUtils.copyProperties(user,resp);
            resp.setDeptName(user.getDept().getName());
            resp.setDeptId(user.getDept().getId());
            /*String roleName = user.getRoles().stream().map(Role::getRoleName).collect(Collectors.joining(","));
            List<Long> collect1 = user.getRoles().stream().map(Role::getId).collect(Collectors.toList());
            resp.setRoleName(roleName);
            resp.setRoleIds(StringUtils.join(collect1, ","));*/
            result.add(resp);
        }
        map.put("data",result);

        return new ResData<>(1, "获取成功", map);
    }

    @GetMapping("/all")
    public Map<String,Object> all(){
        List<User> users = userRepository.findAll();
        Map<Long, String> userIdToName = users.stream().collect(Collectors.toMap(User::getId, User::getUserName));
        List<Dept> depts = deptRepository.findAll();
        Map<Long, String> deptIdToName = depts.stream().collect(Collectors.toMap(Dept::getId, Dept::getName));
        Map<String,Object> result = new HashMap<>();
        result.put("users",userIdToName);
        result.put("depts",deptIdToName);
        return result;
    }

}
